﻿using Abp.Domain.Entities;
using Batman.Cms.Core.Core.SimpleMaintenance.DTO;
using Batman.Cms.Core.Core.SimpleMaintenance.DTO.ActionBar;
using Batman.Cms.Core.Core.SimpleMaintenance.DTO.Column;
using Batman.Cms.Core.Core.SimpleMaintenance.DTO.CreateForm;
using Batman.Cms.Core.Core.SimpleMaintenance.DTO.FormField;
using Batman.Cms.Core.Core.SimpleMaintenance.Enums;
using Omu.ValueInjecter;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Batman.Cms.Core.Core.SimpleMaintenance
{
    public interface IMaintenanceModel
    {
        string Id { get; }

        MaintenanceMainTable MainTable { get; set; }

        Type GetEntityType();
    }

    public class MaintenanceModel<T> : IMaintenanceModel where T : IEntity<string>
    {
        /// <summary>
        /// 主键字段
        /// </summary>
        public string PrimaryKey { get; set; }

        public MaintenanceMainTable MainTable { get; set; }

        public MaintenanceSearchBar<T> SearchBar { get; set; }

        public MaintenceActionBar ActionBar { get; set; }

        public MaintenanceCreateForm CreateForm { get; set; }

        public MaintenanceUpdateForm UpdateForm { get; set; }


        private List<Expression<Func<T, object>>> Includes { get; set; }

        /// <summary>
        /// 排序
        /// </summary>
        private KeyValuePair<Expression<Func<T, object>>, OrderBy> Sort { get; set; }

        public string Id { get { return typeof(T).Name; } }

        private Type _entityType;

        public MaintenanceModel()
        {
            MainTable = new MaintenanceMainTable();
            SearchBar = new MaintenanceSearchBar<T>();
            ActionBar = new MaintenceActionBar();
            CreateForm = new MaintenanceCreateForm();
            UpdateForm = new MaintenanceUpdateForm();
            Includes = new List<Expression<Func<T, object>>>();
            _entityType = typeof(T);
        }

        public Type GetEntityType()
        {
            return _entityType;
        }

        #region 搜索条件


        #endregion

        /// <summary>
        /// 设置主键字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="property"></param>
        public void HasKey<TResult>(Expression<Func<T, TResult>> property)
        {
            this.PrimaryKey = GetSmallHumpWord(property);
        }

        /// <summary>
        /// 操作选项
        /// </summary>
        /// <param name="action"></param>
        public void HasAction(MaintenceAction action)
        {
            ActionBar.Actions.Add(action);
        }


        #region 表格

        /// <summary>
        /// 是否有多选列
        /// </summary>
        /// <param name="has"></param>
        public void HasSelection(bool has = true)
        {
            this.MainTable.HasSelection = has;
        }

        /// <summary>
        /// 连带查询出数据
        /// </summary>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="include"></param>
        public void HasInclude(Expression<Func<T, object>> include)
        {
            this.Includes.Add(include);
        }

        /// <summary>
        /// 设置连查
        /// </summary>
        /// <returns></returns>
        public List<Expression<Func<T, object>>> GetIncludes()
        {
            return this.Includes;
        }

        /// <summary>
        /// 设置读取API
        /// </summary>
        /// <param name="url"></param>
        public void TableReadAction(string url)
        {
            this.MainTable.ReadAction = url;
        }

        /// <summary>
        /// 添加列表字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="label"></param>
        /// <param name="expression"></param>
        public void HasTextColumn<TResult>(string label, Expression<Func<T, TResult>> expression)
        {
            var propName = GetSmallHumpWord(expression);
            this.MainTable.Columns.Add(new TextColumn(label, propName));
        }

        /// <summary>
        /// 添加列表字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="label"></param>
        /// <param name="propExpression"></param>
        public void HasImageColumn<TResult>(string label, Expression<Func<T, TResult>> propExpression, string path = "")
        {
            var propName = GetSmallHumpWord(propExpression);
            this.MainTable.Columns.Add(new ImageColumn(label, propName, path));
        }

        /// <summary>
        /// 添加列表字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="label"></param>
        /// <param name="expression"></param>
        public void HasLinkColumn<TResult>(string label, Expression<Func<T, TResult>> expression)
        {
            var propName = GetSmallHumpWord(expression);
            this.MainTable.Columns.Add(new LinkColumn(label, propName));
        }


        /// <summary>
        /// 添加列表字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="label"></param>
        /// <param name="expression"></param>
        public void HasSwitchColumn<TResult>(string label, Expression<Func<T, TResult>> expression, SwitchColumn other = null)
        {
            var propName = GetSmallHumpWord(expression);

            if (other != null)
            {
                other.Label = label;
                other.Prop = propName;
                this.MainTable.Columns.Add(other);
            }
            else
            {
                var column = new SwitchColumn(label, propName);
                this.MainTable.Columns.Add(column);
            }
        }

        /// <summary>
        /// 设置默认排序
        /// </summary>
        /// <param name="expression"></param>
        public void DefaultSort(Expression<Func<T, object>> expression, OrderBy orderBy)
        {
            this.Sort = new KeyValuePair<Expression<Func<T, object>>, OrderBy>(expression, orderBy);
        }

        public KeyValuePair<Expression<Func<T, object>>, OrderBy> GetSort()
        {
            return Sort;
        }

        #endregion

        /// <summary>
        /// 设置新建表单的处理地址
        /// </summary>
        /// <param name="actionUrl"></param>
        public void CreateFormAction(string actionUrl)
        {
            this.CreateForm.Action = actionUrl;
        }

        /// <summary>
        /// 新建表单字段
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="property"></param>
        /// <param name="formField"></param>
        public void HasCreateFormField<TResult>(Expression<Func<T, TResult>> property, MaintenanceFormField formField)
        {
            formField.FieldName = GetSmallHumpWord(property);
            CreateForm.Fields.Add(formField);
        }

        /// <summary>
        /// 更新表单
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="property"></param>
        /// <param name="formField"></param>
        public void HasUpdateFormField<TResult>(Expression<Func<T, TResult>> property, MaintenanceFormField formField)
        {
            formField.FieldName = GetSmallHumpWord(property);
            UpdateForm.Fields.Add(formField);
        }

        public void HasUpdateAction(string url)
        {
            this.UpdateForm.Action = url;
        }

        /// <summary>
        /// 配置读取数据地址
        /// </summary>
        /// <param name="url"></param>
        public void UpdateFormHasReadAction(string url)
        {
            this.UpdateForm.ReadAction = url;
        }

        /// <summary>
        /// 获取到小驼峰
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="property"></param>
        /// <returns></returns>
        private string GetSmallHumpWord<TResult>(Expression<Func<T, TResult>> property)
        {
            var name = (property.Body as MemberExpression).Member.Name;
            if (string.IsNullOrEmpty(name) || name.Length == 1) return name;

            name = char.ToLower(name[0]) + name.Substring(1);
            return name;
        }
    }
}
